﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Ordinapoche.Core
{
    public class AssemblerInstruction
    {
        private string _Label;
        private string _DataText;
        private string _Comment;

        private int? _Location;            
        private int _DataValue;

        protected int DataValue
        {
            get
            {
                return _DataValue;
            }
        }

        protected void RegisterSymbol (int? aValue, IDictionary<string, int> aSymbols)
        {
            int existingval;
            if (String.IsNullOrEmpty (_Label) || !aValue.HasValue)
            {
                return;
            }


            if (aSymbols.TryGetValue (_Label, out existingval))
            {
                if (aValue.Value != existingval)
                {
                    throw new Exception (String.Format ("The label {0} had value {1} and has now the value {2}", _Label, existingval, aValue.Value));
                }
            }
            else
            {
                aSymbols.Add (_Label, aValue.Value);
            }
        }

        protected void Inc (ref int? aValue)
        {
            if (aValue.HasValue)
            {
                aValue = aValue.Value + 1;
            }
        }

        /// <summary>
        ///     Try to resolve the _DataText to actual numerical data.
        /// </summary>
        /// <param name="aSymbols">
        ///     The set of symbolic names that can be used to map names to values
        /// </param>
        /// <param name="aLastChance">
        ///     Whether it is the last chance to do the mapping. If the mapping fails,
        ///     the function should throw an exception with appropriate information.
        /// </param>
        /// <returns>
        ///     True if the mapping is complete, false if it was not possible.
        ///     Typically, the mapping is not feasible if all symbols are not yet known.
        /// </returns>

        protected virtual bool ComputeData (IDictionary<string, int> aSymbols, bool aLastChance)
        {
            return true;
        }

        public virtual bool ResolveSymbolsPass (ref int? aLocation, IDictionary<string, int> aSymbols, bool aLastChance)
        {
            return true;
        }

        /// <summary>
        ///     Generate the executable file
        /// </summary>
        /// <param name="aLocation">
        ///     The expected location. Typically the expected location should be the same
        ///     as the recorded location.
        /// </param>
        /// <param name="aExecutableFile">
        ///     The executable file in the form of pairs (address, data)
        ///     A typical instruction will add one entry in the executable, corresponding to its data at its
        ///     expected address.
        /// </param>

        public virtual void GeneratePass (ref int aLocation, IDictionary<int, int> aExecutableFile)
        {
        }
    }
}
